
package avl.sv.server.training;

import avl.sv.server.KeyValueRef;
import avl.sv.server.PropertiesManager;
import avl.sv.server.PasswordHash;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import oracle.kv.Key;
import oracle.kv.ValueVersion;

/**
 *
 * @author benbryan
 */
public class TrainingSessionManager {
    
    private static HashMap<String, Session> sessions = new HashMap<>();
    private static TrainingSessionManager instance = null;
    private TrainingSessionManager() { 
        TimerTask purgeUserTask = new TimerTask() {
            @Override
            public void run() {
                try{
                    purgeExpiredSessions();
                } catch (Exception ex){
                    Logger.getLogger(getClass().getName()).log(Level.SEVERE, "", ex);
                }
            }
        };
        Timer purgeUserTimer = new Timer();
        int timeout = 1000*60/10*PropertiesManager.getUserSessionTimeoutMinutes();
        purgeUserTimer.schedule(purgeUserTask, timeout, timeout);
    }
    
    private void purgeExpiredSessions(){
        int timeout = PropertiesManager.getUserSessionTimeoutMinutes();
        if (timeout <= 0){
            return;
        }
        if (sessions == null){
            return;
        }
        for (Session session:sessions.values()){
            long timeSinceLastLogin = (new Date()).getTime()-session.getLastActivity().getTime();
            if (timeSinceLastLogin*1000*60 > timeout){
                sessions.remove(session.getUsername());
            }
        }        
    }
    
    public static TrainingSessionManager getInstance(){
        if(instance == null){
            instance = new TrainingSessionManager();
        }
        return instance;
    }
    
    public String login( String sessionID, String username, String password){
        try {
            final String INVALID = "error: Invalid username or password";
            ArrayList<String> major = new ArrayList<>();
            major.add("user");
            major.add(username);
            ArrayList<String> minor = new ArrayList<>();
            minor.add("password");
            ValueVersion vv = KeyValueRef.getRef().get(Key.createKey(major, minor));
            if (vv == null) {
                // Not a user
                return INVALID;
            }
            String storeHash = new String(vv.getValue().getValue());
            if (PasswordHash.validatePassword(password, storeHash)) {
                removeUserSession(username);
                Session session = new Session(new Date(), username);
                sessions.put(sessionID, session);
                return sessionID;
            } else {
                // Wrong password
                return INVALID;
            }
        } catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
            ex.printStackTrace(System.out);
            return "error: Login error on server side";
        }
    }
    
    private String createSessionID() {
        return Integer.toHexString((int) (Math.random() * Integer.MAX_VALUE))
                + Integer.toHexString((int) (Math.random() * Integer.MAX_VALUE))
                + Integer.toHexString((int) (Math.random() * Integer.MAX_VALUE))
                + Integer.toHexString((int) (Math.random() * Integer.MAX_VALUE));
    }
    
    public String getUsername(String sessionID) {
        //Remove this user entry if presesnt
        Session session = sessions.get(sessionID);
        if (session == null) {
            return null;
        }
        session.setLastActivity(new Date());
        String username = session.getUsername();
//        System.out.println("Action by: " + username);
        return username;
    }
    
    public void removeUserSession(String username) {
        //Remove this user entry if presesnt
        Iterator<Map.Entry<String, Session>> sessionIter = sessions.entrySet().iterator();
        while (sessionIter.hasNext()) {
            Map.Entry<String, Session> session = sessionIter.next();
            if (session.getValue().getUsername().equals(username)) {
                sessions.remove(session.getKey());
                break;
            }
        }
    }
    
    
    
}
